using System.Xml.Linq;
using TestCases.Assertions;

namespace TestCases.XmlAssert
{
    public interface IAAssertAnd
    {
        IAAssert And { get; }
    }

    public interface IAAssert
    {
        IAAssertAnd Attribute(string name);
        IAAssertAnd Attribute(QualifyForm form, string name);

        IAAssertAnd Attribute(string name, string value);
        IAAssertAnd Attribute(QualifyForm form, string name, string value);
    }

    internal class AttributeAssert : AssertBase, IAAssert, IAAssertAnd
    {
        private readonly XElement _element;

        public AttributeAssert(IAssertion assertion, XElement element) : base(assertion)
        {
            _element = element;
        }

        public IAAssertAnd Attribute(string name)
        {
            AssertAttribute(QualifyForm, name);
            return this;
        }

        public IAAssertAnd Attribute(QualifyForm form, string name)
        {
            AssertAttribute(form, name);
            return this;
        }

        public IAAssertAnd Attribute(string name, string value)
        {
            return Attribute(QualifyForm, name, value);
        }

        public IAAssertAnd Attribute(QualifyForm form, string name, string value)
        {
            XAttribute attr = AssertAttribute(form, name);
            Assert(attr.Value == value, "Attribute <{0}> has illegal value. Expected:<{1}>. Actual:<{2}>.",
                name, value, attr.Value);
            return this;
        }

        public IAAssert And
        {
            get { return this; }
        }

        private XAttribute AssertAttribute(QualifyForm form, string name)
        {
            XAttribute attr = _element.Attribute(GetName(form, name));
            Assert(attr != null, "Attribute <{0}> is not valid.", name);
            return attr;
        }
    }
}